﻿/*
 * Rappelz: Endless Odyssey - The first free open source Rappelz server emulator
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rappelz.GameServer.Network;
using System.Data.Common;
using System.Data;
using Rappelz.GameServer.Network.GameClient;

namespace Rappelz.GameServer.Database
{
    /// <summary>
    /// DBLoader_Skill
    /// </summary>
    public class DBLoader_Skill : IDBProc
    {
        GameDBManager db;
        public BaseObject m_CBObject = null;

        private enum DBFields : int
        {
            AccountId = 0,
        }

        public DBLoader_Skill(GameDBManager dbManager)
        {
            db = dbManager;
        }

        public void SetCB(BaseObject obj)
        {
            m_CBObject = obj;
        }

        public void RunCB()
        {
            if (m_CBObject != null)
                m_CBObject.onEndQuery();
        }

        public bool onProcess()
        {
            DbConnection conn = db.CreateConnection();

            LoadSkillData(conn);
            LoadSkillJPData(conn);
            LoadSkillTreeData(conn);
            return true;
        }

        private bool LoadSkillData(DbConnection conn)
        {
            DbCommand cmd = conn.CreateCommand();
            cmd.CommandText = "select * from SkillResource";
            cmd.CommandType = CommandType.Text;

            int off = 0;
            conn.Open();
            int count = 0;
            try
            {
                DbDataReaderTypeCastHelper dr = new DbDataReaderTypeCastHelper(cmd.ExecuteReader());
                while (dr.Read())
                {
                    off = 0;
                    SkillBase sb = new SkillBase();
                    sb.uid = dr.GetInt32(off++);
                    sb.name_id = dr.GetInt32(off++);
                    int desc_id = dr.GetInt32(off++);
                    int tooltip_id = dr.GetInt32(off++);
                    sb.is_valid = dr.GetByte(off++);
                    sb.elemental = dr.GetByte(off++);
                    sb.is_active = dr.GetByte(off++);
                    sb.is_spell_act = dr.GetByte(off++);
                    sb.is_harmful = dr.GetByte(off++);
                    sb.is_need_target = dr.GetByte(off++);
                    sb.is_corpse = dr.GetByte(off++);
                    sb.is_toggle = dr.GetByte(off++);
                    sb.toggle_group = dr.GetInt32(off++);
                    sb.cancel_type = dr.GetByte(off++);
                    sb.cancel_level = dr.GetByte(off++);
                    sb.cast_range = dr.GetInt32(off++);
                    sb.valid_range = dr.GetInt32(off++);
                    sb.cost_hp = dr.GetInt32(off++);
                    sb.cost_hp_per_skl = dr.GetInt32(off++);
                    sb.cost_mp = dr.GetInt32(off++);
                    sb.cost_mp_per_skl = dr.GetInt32(off++);
                    sb.cost_mp_per_enhance = dr.GetInt32(off++);
                    sb.cost_hp_per = (float)dr.GetDecimal(off++);
                    sb.cost_hp_per_skl_per = (float)dr.GetDecimal(off++);
                    sb.cost_mp_per = (float)dr.GetDecimal(off++);
                    sb.cost_mp_per_skl_per = (float)dr.GetDecimal(off++);

                    sb.cost_havoc = dr.GetInt32(off++);
                    sb.cost_havoc_per_skl = dr.GetInt32(off++);
                    sb.cost_energy = (float)dr.GetDecimal(off++);
                    sb.cost_energy_per_skl = (float)dr.GetDecimal(off++);
                    sb.cost_exp = dr.GetInt32(off++);
                    sb.cost_exp_per_enhance = dr.GetInt32(off++);
                    sb.cost_jp = dr.GetInt32(off++);

                    sb.cost_jp_per_enhance = dr.GetInt32(off++);
                    sb.cost_item = dr.GetInt32(off++);
                    sb.cost_item_count = dr.GetInt32(off++);
                    sb.cost_item_count_per_skl = dr.GetInt32(off++);
                    sb.need_level = dr.GetInt32(off++);
                    sb.need_hp = dr.GetInt32(off++);
                    sb.need_mp = dr.GetInt32(off++);
                    sb.need_havoc = dr.GetInt32(off++);
                    sb.need_havoc_burst = dr.GetInt32(off++);
                    sb.need_state_id = dr.GetInt32(off++);
                    sb.need_state_level = dr.GetByte(off++);
                    sb.need_state_exhaust = dr.GetByte(off++);
                    sb.vf_one_hand_sword = dr.GetByte(off++);
                    sb.vf_two_hand_sword = dr.GetByte(off++);
                    sb.vf_double_sword = dr.GetByte(off++);

                    sb.vf_dagger = dr.GetByte(off++);
                    sb.vf_double_dagger = dr.GetByte(off++);
                    sb.vf_spear = dr.GetByte(off++);
                    sb.vf_axe = dr.GetByte(off++);
                    sb.vf_one_hand_axe = dr.GetByte(off++);
                    sb.vf_double_axe = dr.GetByte(off++);
                    sb.vf_one_hand_mace = dr.GetByte(off++);
                    sb.vf_two_hand_mace = dr.GetByte(off++);
                    sb.vf_lightbow = dr.GetByte(off++);
                    sb.vf_heavybow = dr.GetByte(off++);
                    sb.vf_crossbow = dr.GetByte(off++);
                    sb.vf_one_hand_staff = dr.GetByte(off++);
                    sb.vf_two_hand_staff = dr.GetByte(off++);
                    sb.vf_shield_only = dr.GetByte(off++);
                    sb.vf_is_not_need_weapon = dr.GetByte(off++,0);
                    sb.delay_cast = (uint)(float)(dr.GetDecimal(off++) * 100);
                    sb.delay_cast_per_skl = (uint)(float)(dr.GetDecimal(off++)*100);

                    sb.delay_cast_mod_per_enhance = (float)dr.GetDecimal(off++);
                    sb.delay_common = (uint)(float)(dr.GetDecimal(off++) * 100);
                    sb.delay_cooltime = (uint)(float)(dr.GetDecimal(off++) * 100);
                    float delay_cooltime_per_skl = (uint)(float)(dr.GetDecimal(off++) * 100);
                    sb.delay_cooltime_mod_per_enhance = (float)dr.GetDecimal(off++);
                    sb.cool_time_group_id = dr.GetInt32(off++);
//                    sb.unkf1 = (float)dr.GetDecimal(off++);
                    sb.uf_self = dr.GetByte(off++);
                    sb.uf_party = dr.GetByte(off++);
                    sb.uf_guild = dr.GetByte(off++);
                    sb.uf_neutral = dr.GetByte(off++);
                    sb.uf_purple = dr.GetByte(off++);
                    sb.uf_enemy = dr.GetByte(off++);
                    sb.tf_avatar = dr.GetByte(off++);
                    sb.tf_summon = dr.GetByte(off++,0);
                    sb.tf_monster = dr.GetByte(off++);
                    int skill_lvup_limit = dr.GetByte(off++);
                    sb.target = dr.GetInt16(off++);
                    sb.effect_type = dr.GetInt16(off++);
                    int skill_enchant_link_id = dr.GetInt32(off++);
                    sb.state_id = dr.GetInt32(off++);
                    sb.state_level_base = dr.GetInt32(off++);
                    sb.state_level_per_skl = (float)dr.GetDecimal(off++);
                    sb.state_level_per_enhance = (float)dr.GetDecimal(off++);
                    sb.state_second = (uint)(float)(dr.GetDecimal(off++)*100);
                    sb.state_second_per_skl = (uint)(float)(dr.GetDecimal(off++) * 100);
                    sb.state_second_per_enhance = (uint)(float)(dr.GetDecimal(off++) * 100);
//                    sb.state_type = dr.GetByte(off++);
                    sb.probability_on_hit = dr.GetInt32(off++);
                    sb.probability_inc_by_slv = dr.GetInt32(off++);
                    sb.hit_bonus = dr.GetInt16(off++);
                    sb.hit_bonus_enhance = dr.GetInt16(off++);
                    sb.percentage = dr.GetInt16(off++);
                    sb.hate_mod = (float)dr.GetDecimal(off++);
                    sb.hate_basic = dr.GetInt16(off++);
                    sb.hate_slv = (float)dr.GetDecimal(off++);
                    sb.hate_enhance = (float)dr.GetDecimal(off++);
                    sb.critical_bonus = dr.GetInt32(off++);
                    sb.critical_bonus_per_skl = dr.GetInt32(off++);
                    for(int v = 0; v < 20;++v)
                    {
                        sb.m_var[v] = (float)dr.GetDecimal(off++);
                    }

                    int icon_id = dr.GetInt32(off++);
                    string icon_file_name = dr.GetString(off++);
                    sb.is_projectile = dr.GetByte(off++);
                    sb.projectile_speed = (float)dr.GetDecimal(off++);
                    sb.projectile_acceleration = (float)dr.GetDecimal(off++);

                    sb.effect_flag = 0;
                    if (sb.effect_type == 301)
                        sb.effect_flag = 2;
                    GameContent.RegisterSkillBase(sb);

                    count++;
                }
            }
            catch (System.Data.SqlClient.SqlException e)
            {
                Globals.Log.Warning("Can't load SkillResource database, Sql string: {0}", e.Message);
            }
            catch (Exception ex)
            {
                Globals.Log.Error("DBLoader_Skill.LoadSkillData Exception: {0}", ex);
            }
            conn.Close();
            Globals.Log.Info("Total {0} SkillResource loaded.", count);
            return true;
        }

        private bool LoadSkillJPData(DbConnection conn)
        {
            DbCommand cmd = conn.CreateCommand();
            cmd.CommandText = "select * from SkillJPResource";
            cmd.CommandType = CommandType.Text;

            conn.Open();
            int count = 0;
            try
            {
                DbDataReaderTypeCastHelper dr = new DbDataReaderTypeCastHelper(cmd.ExecuteReader());
                while (dr.Read())
                {
                    int off = 0;
                    int skill_id = dr.GetInt32(off++);
                    SkillBase sb = GameContent.GetSkillBase(skill_id);
                    if(sb != null)
                    {
                        for(int v = 0; v < 50; ++v)
                        {
                            sb.m_need_jp[v] = dr.GetInt32(off++);
                        }
                        count++;
                    }
                }
            }
            catch (System.Data.SqlClient.SqlException e)
            {
                Globals.Log.Warning("Can't load SkillJPResource database, Sql string: {0}", e.Message);
            }
            catch (Exception ex)
            {
                Globals.Log.Error("DBLoader_Skill.LoadSkillJPData Exception: {0}", ex);
            }
            conn.Close();
            Globals.Log.Info("Total {0} SkillJPResource loaded.", count);
            return true;

        }

        private bool LoadSkillTreeData(DbConnection conn)
        {
            DbCommand cmd = conn.CreateCommand();
            cmd.CommandText = "select * from SkillTreeResource";
            cmd.CommandType = CommandType.Text;

            conn.Open();
            int count = 0;
            try
            {
                DbDataReaderTypeCastHelper dr = new DbDataReaderTypeCastHelper(cmd.ExecuteReader());
                while (dr.Read())
                {
                    int off = 0;
                    SkillTree st = new SkillTree();
                    st.job_id = dr.GetInt32(off++);
                    st.skill_id = dr.GetInt32(off++);
                    st.min_skill_lv = dr.GetInt32(off++);
                    st.max_skill_lv = dr.GetInt32(off++);
                    st.lv = dr.GetInt32(off++);
                    st.job_lv = dr.GetInt32(off++);
                    st.jp_ratio = (float)dr.GetDecimal(off++);
                    for(int v = 0; v < 3;++v)
                    {
                        st.need_skill_id[v] = dr.GetInt32(off++);
                        st.need_skill_lv[v] = dr.GetInt32(off++);
                    }
                    st.min_stage = dr.GetInt32(off++);
                    st.max_stage = dr.GetInt32(off++);

                    GameContent.RegisterSkillTree(st);
                    count++;
                }
            }
            catch (System.Data.SqlClient.SqlException e)
            {
                Globals.Log.Warning("Can't load SkillTreeResource database, Sql string: {0}", e.Message);
            }
            catch (Exception ex)
            {
                Globals.Log.Error("DBLoader_Skill.LoadSkillTreeData Exception: {0}", ex);
            }
            conn.Close();
            Globals.Log.Info("Total {0} SkillTreeResource loaded.", count);
            return true;

        }

    }

}
